package cn.smile.business.core.impl;

import cn.smile.bean.dto.core.FileUploadDTO;
import cn.smile.bean.dto.core.UploadFileDTO;
import cn.smile.bean.entity.core.FileUpload;
import cn.smile.bean.form.core.file.FileUploadForm;
import cn.smile.bean.form.core.file.FileUploadQueryForm;
import cn.smile.business.core.IFileUploadService;
import cn.smile.commons.constant.CommonConstant;
import cn.smile.commons.constant.NumberConstant;
import cn.smile.commons.domain.BaseServiceImpl;
import cn.smile.repository.core.FileUploadMapper;
import cn.smile.utils.BeanCopy;
import cn.smile.utils.FileUploadUtil;
import cn.smile.utils.UserUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import jakarta.annotation.Resource;

import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 龙逸
 * @since 2022-04-01
 */
@Slf4j
@Service
public class FileUploadServiceImpl extends BaseServiceImpl<FileUploadMapper, FileUpload> implements IFileUploadService {
    @Resource
    private FileUploadUtil fileUploadUtil;

    private static final List<String> FILE_SUFFIX_LIST = Lists.newArrayList(CommonConstant.EXCEL_FILE_SUFFIX_XLSX, CommonConstant.EXCEL_FILE_SUFFIX_XLS);

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String fileUpload(FileUploadForm form) {
        log.info("[FileUploadServiceImpl].[fileUpload] ------> 文件上传至 MinIO Start");
        //上传文件
        UploadFileDTO fileDTO = fileUploadUtil.uploadFile(form.getFile(), form.getIsRename());
        FileUpload info = BeanCopy.copyBean(fileDTO, FileUpload.class);
        info.setUploadTime(LocalDateTime.now());
        info.setUploadUserId(UserUtil.getUserInfo().getId());
        info.setUploadUserName(UserUtil.getUserInfo().getNickName());
        super.addBaseCol(info);
        int insertNum = baseMapper.insert(info);
        log.info("[FileUploadServiceImpl].[fileUpload] ------> 文件上传至 MinIO End, insertNum = {}", insertNum);
        return insertNum > NumberConstant.ZERO ? info.getId() : null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void autoDelFile() {
        log.info("[FileUploadServiceImpl].[fileUpload] ------> 自动删除 MinIO 文件 Start");
        for (String fileSuffix : FILE_SUFFIX_LIST) {
            List<FileUpload> fileList = baseMapper.selectList(new QueryWrapper<FileUpload>().lambda().eq(FileUpload::getDeleted, Boolean.FALSE).like(FileUpload::getNewFileName, fileSuffix).le(FileUpload::getCreateTime, LocalDateTime.now().minusDays(NumberConstant.THIRTY)));
            List<String> fileNames = Lists.newArrayList();
            if (!CollectionUtils.isEmpty(fileList)) {
                fileList.forEach(file -> {
                    fileNames.add(file.getNewFileName());
                    super.delBaseCol(file);
                    baseMapper.updateById(file);
                });
                fileUploadUtil.delFile(fileNames);
            }
        }
        log.info("[FileUploadServiceImpl].[fileUpload] ------> 自动删除 MinIO 文件 End");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String miniUpload(MultipartFile file) {
        log.info("[FileUploadServiceImpl].[miniUpload] ------> 微信小程序上传图片至 MinIO Start");
        FileUploadForm form = new FileUploadForm();
        form.setFile(file);
        String id = this.fileUpload(form);
        FileUpload upload = baseMapper.selectById(id);
        String url = ObjectUtils.isEmpty(upload) ? null : upload.getDownloadUrl();
        log.info("[FileUploadServiceImpl].[miniUpload] ------> 微信小程序上传图片至 MinIO End, url = {}", url);
        return url;
    }

    @Override
    public List<FileUploadDTO> getFileList(FileUploadQueryForm form) {
        log.info("[FileUploadServiceImpl].[getFileList] ------> 查询文件上传记录 Start, form = {}", JSON.toJSONString(form));
        LambdaQueryWrapper<FileUpload> qw = this.getQueryParams(form);
        List<FileUpload> baseList = baseMapper.selectList(qw);
        List<FileUploadDTO> dataList = BeanCopy.copyList(baseList, FileUploadDTO.class);
        log.info("[FileUploadServiceImpl].[getFileList] ------> 查询文件上传记录 End");
        return dataList;
    }

    @Override
    public Boolean delFileById(String id) {
        log.info("[FileUploadServiceImpl].[delFileById] ------> 删除文件上传记录及文件 Start, id = {}", id);
        FileUpload entity = super.get(id);
        if (!ObjectUtils.isEmpty(entity.getNewFileName())) {
            fileUploadUtil.delFile(Lists.newArrayList(entity.getNewFileName()));
        }
        int delNum = baseMapper.deleteById(id);
        log.info("[FileUploadServiceImpl].[delFileById] ------> 删除文件上传记录及文件 End, delNum = {}", delNum);
        return delNum > NumberConstant.ZERO;
    }

    /**
     * 组装数据库查询条件
     *
     * @param form 查询参数
     * @return 数据库查询条件
     */
    private LambdaQueryWrapper<FileUpload> getQueryParams(FileUploadQueryForm form) {
        LambdaQueryWrapper<FileUpload> qw = new QueryWrapper<FileUpload>().lambda().eq(FileUpload::getDeleted, Boolean.FALSE);
        if (!ObjectUtils.isEmpty(form.getOldFileName())) {
            qw.like(FileUpload::getOldFileName, form.getOldFileName());
        }
        if (!ObjectUtils.isEmpty(form.getNewFileName())) {
            qw.like(FileUpload::getNewFileName, form.getNewFileName());
        }
        if (!ObjectUtils.isEmpty(form.getBucketName())) {
            qw.eq(FileUpload::getBucketName, form.getBucketName());
        }
        if (!ObjectUtils.isEmpty(form.getUploadTimeStart())) {
            qw.ge(FileUpload::getUploadTime, form.getUploadTimeStart());
        }
        if (!ObjectUtils.isEmpty(form.getUploadTimeEnd())) {
            qw.le(FileUpload::getUploadTime, form.getUploadTimeEnd());
        }
        return qw;
    }
}
